/*------------------------------------------------------------------------
|                            FILE DESCRIPTION                            |
------------------------------------------------------------------------*/
/*------------------------------------------------------------------------
|  - File name     : os_task.h
|  - Author        : zeweni
|  - Update date   : 2021.05.05
|  - Copyright(C)  : 2021-2021 zeweni. All rights reserved.
------------------------------------------------------------------------*/
/*------------------------------------------------------------------------
|                            COPYRIGHT NOTICE                            |
------------------------------------------------------------------------*/
/*
 * Copyright (C) 2021, zeweni (17870070675@163.com)

 * This file is part of Ant Real Time Operating System.

 * Ant Real Time Operating System is free software: you can redistribute 
 * it and/or modify it under the terms of the Apache-2.0 License.

 * Ant Real Time Operating System is distributed in the hope that it will 
 * be useful,but WITHOUT ANY WARRANTY; without even the implied warranty 
 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
 * Apache-2.0 License License for more details.

 * You should have received a copy of the Apache-2.0 License.Ant Real Time
 * Operating System. If not, see <http://www.apache.org/licenses/>.
**/
/*------------------------------------------------------------------------
|                                INCLUDES                                |
------------------------------------------------------------------------*/

#include "os_core.h"
#include "os_cpu.h"
#include "os_mem.h"
#include "os_thread.h"
#include "os_object.h"

/*------------------------------------------------------------------------
|                               DECLARATION                              |
------------------------------------------------------------------------*/

/**
 * @brief     初始化空闲线程。仅限本文件内调用。
 * @details   Initialize idle threads.
 *            It can only be called within this file.
**/
#define  OS_IDLE_THREAD_INIT()                         \
do{                                                    \
	OS_CREATE_STATIC_THREAD(OS_Idle_Thread,            \
	                        0,                         \
							AntOS_Idle_Thread,         \
							OS_NULL,                   \
							0,                         \
							Idle_Stack,                \
							OS_IDLE_THREAD_STK_SIZE,   \
							65535);                    \
}while(0)                                                 


/*------------------------------------------------------------------------
|                                  DATA                                  |
------------------------------------------------------------------------*/

/**
 * @brief   空闲线程堆栈。
 * @details Idle thread stack.
**/
extern OS_Thread_Stk Idle_Stack[OS_IDLE_THREAD_STK_SIZE];


/**
 * @brief   空闲线程的指针句柄。
 * @details The pointer handle of the idle thread.
**/
extern OS_Thread_t OS_Idle_Thread; 

/**
  * @name    G_OS_Stack
  * @brief   RTOS kernel stack.
***/
struct OS_Kernel_Stk volatile idata Kernel_Stack;

/**
 * @brief   RTOS access external RAM pointer.
**/
os_uint8_t xdata * data G_pXRAMStk; 

/**
 * @brief   RTOS accesses the internal RAM pointer..
**/
os_uint8_t idata * data G_pRAMStk; 

/**
 * @brief   系统异常代号，存系统发生异常时，对应问题的代号值。
 * @details System abnormality code, save the code value 
 *          corresponding to the problem when the system is abnormal.
**/
static os_uint8_t G_Exc_Code;


/**
 * @brief    空闲函数入口句柄地址。
 * @details  RTOS idle task handle function.
**/
OS_Idle_Thread_Handle_t OS_Idle_Excute = OS_NULL;
 
/**
 * @brief   空闲线程的指针句柄。
 * @details The pointer handle of the idle thread.
**/
 OS_Thread_t OS_Idle_Thread;

/*------------------------------------------------------------------------
|                              API FUNCTIONS                             |
------------------------------------------------------------------------*/

/**
 * @brief     空闲线程，用于任务调度，默认被创建。
 * @details   Idle thread, used for task scheduling, is created by default.
 * @param     None.
 * @return    None.
**/
void AntOS_Idle_Thread(void);


/**
 * @brief   OS初始化系统调度器，选择最高优先级的任务执行。
 * @details OS starts system scheduling and selects the highest priority task for execution.
 * @param   None.
 * @retval  None.
**/
extern void OS_Scheduler_Init(void);

/**
 * @brief     获取就绪线程队列链表中优先级最高的线程。
 * @details   Get the thread with the highest priority in the ready thread list.
 * @param[in] maxPriLabel 最高优先级的线程标号。The thread label with the highest priority.
 * @return    [OS_Thread_t]  更新成功,返回最高优先级的地址。 Update completed.
 * @return    [OS_NULL] 更新失败或者就绪线程链表为空。
 *                      The update failed or the ready thread list is empty.
**/
extern OS_Thread_t OS_RdyList_Get_MaxPrio(os_uint8_t *maxPriLabel);

/**
 * @brief     更新线程链表。
 * @details   Update the thread list.
 * @param     list 链表地址。Linked list address.
 * @return    None.
**/
extern void OS_Update_List(OS_Thread_t list);

/**
 * @brief   OS初始化启动代码,该函数在main之前执行。
 * @details OS initializes the startup code, and this function is executed before main.
 * @param   None.
 * @return  [OS_OK] 初始化成功。Ant RTOS initailized successfully. 
 * @return  [OS_NOK]初始化失败。 Ant RTOS initailized failed. 
**/
int OS_Startup_Init(void)
{
	G_LockCnt = 0;  /*!< 初始化系统临界锁计数器。*/
	
	G_Exc_Code = 0; /*!< 初始化系统异常代号值。*/
	
	AntOS_Board_Init();  /*!< 初始化系统板极支持包，需要用户自己实现这个同名函数。*/
	
	OS_ENTER_CRITICAL();  /*!< 进入临界区 */
	
	AntOS_Mem_Init();  /*!< 初始化系统内存管理 */
	
	OS_IDLE_THREAD_INIT();  /*!< 初始化并创建空闲线程 */
	
	AntOS_Main();  /*!< 调用OS的main函数 */

	OS_Scheduler_Init();  /*!< 初始化线程调度器 */
	
    return 0;
}


/**
 * @brief   OS异常处理函数。
 * @details OS exception handling function.
 * @param   excCode 异常代号.Exception code.
 * @return  None.
 * @note    OS运行出现差错时，回调这个异常处理函数，用来指示出现的错误。
 *          When there is an error in the OS operation, 
 *          this exception handling function is called back to indicate the error.
**/
void OS_Exce_Handle(os_uint8_t excCode)
{
	OS_ENTER_CRITICAL();
	G_Exc_Code = excCode;
	while(1);
}


/**
 * @brief     空闲线程，用于任务调度，默认被创建。
 * @details   Idle thread, used for task scheduling, is created by default.
 * @param     None.
 * @return    None.
**/
void AntOS_Idle_Thread(void)
{

    /**
     * @brief     线程4的入口函数。
     * @details   Entry function of thread 5.
     * @param[in] param 线程5的入口参数。
     * @return    None
    **/
    extern os_err_t OS_Mem_Recycle(void);

	for(;;)
	{
		
		/* If user will be use idle task handle function, run it.*/
		if(OS_Idle_Excute)
		{
			OS_Idle_Excute();
		}
//		OS_Mem_Recycle();
	}
}


/**
 * @brief   MCU TIMER0 Interrupt request service function
 * @param   None
 * @return  None
**/
void OS_Update_Ticks_Handle(void)
{
	os_uint8_t index = 0;   /*!< 休眠线程计数变量。
	                              Count variable of sleeping threads. */
	os_uint8_t slpEndCtr = 0; /*!< 休眠线程结束统计变量。
	                                Count variable for the end of the sleeping threads. */
    os_uint8_t maxPriLabel = 0;
	os_bool_t SliEndMark = OS_FALSE;
	OS_Thread_t *thread = OS_NULL;
	
	OS_ENTER_CRITICAL();
	
	if ( (*G_OS_Thread_RunNode)->SliCtr == 0 )
	{
		(*G_OS_Thread_RunNode)->SliCtr = (*G_OS_Thread_RunNode) -> TickSlice;
		SliEndMark = OS_TRUE;
	}else
	{
		(*G_OS_Thread_RunNode)->SliCtr--;
	}
	
	if (G_OS_Thread_SlpList.Num)
	{
		for (index = 0; index < OS_THREAD_MAX_NUM; index++)
		{
			if (G_OS_Thread_SlpList.Node[index] != OS_NULL)
			{
				/** 如果有任务休眠时间结束，就将其加入就链表。*/
				if (-- ((OS_Thread_t ) *G_OS_Thread_SlpList.Node[index])->SlpCtr == 0)
				{
					((OS_Thread_t ) *G_OS_Thread_SlpList.Node[index])->Status = OS_THREAD_READY;
					G_OS_Thread_RdyList.Node[G_OS_Thread_RdyList.Num++] = G_OS_Thread_SlpList.Node[index];
					
					G_OS_Thread_SlpList.Node[index] = OS_NULL;
					slpEndCtr++;
				}
			}
		}	
	}

	G_OS_Thread_SlpList.Num -= slpEndCtr;
	
	/** 如果有任务休眠完成，或者有更高优先级的任务就绪，立刻发生线程调度 */
	if (slpEndCtr > 0 || SliEndMark == OS_TRUE )
	{
		thread = (OS_Thread_t *)OS_RdyList_Get_MaxPrio(&maxPriLabel);
		
		if ((*thread)->Prio > (*G_OS_Thread_RunNode)->Prio)
		{
			(*G_OS_Thread_RunNode) -> Status = OS_THREAD_READY;
		    	OS_Thread_Schedule();
		}
	}
	
	OS_EXIT_CRITICAL();
}


/**
 * @brief   main函数
 * @param   None
 * @return  None
**/
int main(void)
{  
    OS_Exce_Handle(EXC_CODE_ILLEGAL_JUMP);
	return 0;
}


/*------------------------------------------------------------------------
|                    END OF FLIE.  (C) COPYRIGHT zeweni                  |
------------------------------------------------------------------------*/